package execution;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;

public class BaseInterpretter implements Interpretter {
	
	private final String source;
	
	public BaseInterpretter(String filename) throws FileNotFoundException, IOException {
		BufferedReader reader = new BufferedReader(new FileReader(filename));
		StringBuilder sb = new StringBuilder();
		String line;
		while ( (line = reader.readLine()) != null) {
			sb.append(line);
		}
		reader.close();
		source = sb.toString();
	}
	
	public Pair<String, Boolean> compute(InputStream is) {
		String out = "";
		try {
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			Tape tape = new Tape(os, is);
			int i = 0;
			while(i < source.length()) {
				switch (source.charAt(i)) {
				case '>': tape.inc_ptr(); break;
				case '<': tape.dec_ptr(); break;
				case '+': tape.inc(); break;
				case '-': tape.dec(); break;
				case '.': tape.out(); break;
				case ',': tape.in(); break;
				case '[': {
					if (tape.getDatum() == 0) {
						int tempIndex = i+1;
						int neededStart = 1;
						while (neededStart > 0 && tempIndex < source.length()) {
							switch (source.charAt(tempIndex)) {
							case '[': neededStart++; break;
							case ']': neededStart--; break;
							}
							tempIndex++;
						}
						if (tempIndex >= source.length()) throw new UnclosedLoopException('[',i);
						i = tempIndex;
					}
					break;
				}
				case ']': {
					if (tape.getDatum() != 0) {
						int tempIndex = i-1;
						int neededStart = 1;
						while (neededStart > 0 && tempIndex >= 0) {
							switch (source.charAt(tempIndex)) {
							case '[': neededStart--; break;
							case ']': neededStart++; break;
							}
							tempIndex--;
						}
						if (tempIndex < 0) throw new UnclosedLoopException(']',i);
						i = tempIndex;
					}
					break;
				}
				}
				i++;
			}
			return new Pair<String, Boolean>(out, new Boolean(true));
		} catch (UnclosedLoopException e) {
			System.out.println("c-brainfk encountered an unmatched "+e.getUnmatched()+" at position "+e.getBeginIndex());
			return new Pair<String, Boolean>(out, new Boolean(false));
		} catch (IOException e) {
			System.out.println("c-brainfk could not receive input from stream.");
			return new Pair<String, Boolean>(out, new Boolean(false));
		}
	}

}
